package cn.lhn.ridersclub.controller;

import cn.lhn.ridersclub.anno.TokenVerify;
import cn.lhn.ridersclub.dto.Result;
import cn.lhn.ridersclub.entity.Account;
import cn.lhn.ridersclub.entity.Club;
import cn.lhn.ridersclub.entity.ClubClassify;
import cn.lhn.ridersclub.entity.Login;
import cn.lhn.ridersclub.mapper.AccountMapper;
import cn.lhn.ridersclub.mapper.ClubClassifyMapper;
import cn.lhn.ridersclub.mapper.ClubMapper;
import cn.lhn.ridersclub.service.LoginService;
import org.apache.commons.codec.binary.Hex;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.UUID;

@RestController
@RequestMapping("/file")
public class FileController {

    public static final String FILE_BASE_PATH =
            System.getProperty("os.name").toLowerCase().contains("linux")
                    ? "/www/ridersclub/"
                    : "C:/Users/22325/Desktop/ridersclub/";

    private final AccountMapper accountMapper;

    private final ClubMapper clubMapper;

    private final ClubClassifyMapper clubClassifyMapper;

    private final LoginService loginService;

    public FileController(AccountMapper accountMapper, ClubMapper clubMapper, ClubClassifyMapper clubClassifyMapper, LoginService loginService) {
        this.accountMapper = accountMapper;
        this.clubMapper = clubMapper;
        this.clubClassifyMapper = clubClassifyMapper;
        this.loginService = loginService;
    }

    @GetMapping("/header/md5")
    public Result<String> getHeaderImageMD5(Long accountId) {
        FileInputStream in = null;
        try {
            MessageDigest MD5 = MessageDigest.getInstance("MD5");
            in = new FileInputStream(FILE_BASE_PATH + "image/header/" + accountId + ".png");
            byte[] buffer = new byte[8192];
            int length;
            while ((length = in.read(buffer)) != -1) {
                MD5.update(buffer, 0, length);
            }
            String md5 = new String(Hex.encodeHex(MD5.digest()));
            return Result.success("查询成功", md5);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("查询失败");
        } finally {
            try {
                if (in != null){
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @GetMapping("/club/image")
    public void getClubImage(Long clubId, String size, HttpServletResponse response) {
        Club club = clubMapper.selectById(clubId);
        if (club == null) {
            throw new RuntimeException("车友圈不存在");
        }

        if (size == null) {
            throw new RuntimeException("尺寸错误");
        }

        if (!size.equals("1-1") && !size.equals("16-9")) {
            throw new RuntimeException("尺寸错误");
        }

        //  设置响应头
        response.setContentType("application/force-download");
        response.addHeader("Content-Disposition", "attachment;fileName=" + club.getClubName() + "-" + size + ".jpg");

        try {
            FileInputStream in = new FileInputStream(FILE_BASE_PATH + "image/club/" + club.getClubName() + "-" + size + ".jpg");
            ServletOutputStream out = response.getOutputStream();
            byte[] buff = new byte[1024];
            int n;
            while ((n = in.read(buff)) != -1) {
                out.write(buff, 0, n);
                out.flush();
            }

            in.close();
        }
        catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    @GetMapping("/classify/image")
    public void getClassifyImage(Long classifyId, HttpServletResponse response) {

        ClubClassify classify = clubClassifyMapper.selectById(classifyId);

        if (classify == null) {
            throw new RuntimeException("分类不存在");
        }

        //  设置响应头
        response.setContentType("application/force-download");
        response.addHeader("Content-Disposition", "attachment;fileName=" + classify.getClassify() + ".jpg");

        try {
            FileInputStream in = new FileInputStream(FILE_BASE_PATH + "image/classify/" + classify.getClassify() + ".jpg");
            ServletOutputStream out = response.getOutputStream();
            byte[] buff = new byte[1024];
            int n;
            while ((n = in.read(buff)) != -1) {
                out.write(buff, 0, n);
                out.flush();
            }

            in.close();
        }
        catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    @GetMapping("/header/getByEmail")
    public void getHeaderByEmail(String email, HttpServletResponse response) {
        Login login = loginService.getLoginByEmail(email);
        if (login == null) {
            throw new RuntimeException("账号不存在");
        }

        //  设置响应头
        response.setContentType("application/force-download");
        response.addHeader("Content-Disposition", "attachment;fileName=" + login.getId() + ".png");

        try {
            FileInputStream in = new FileInputStream(FILE_BASE_PATH + "image/header/" + login.getId() + ".png");
            ServletOutputStream out = response.getOutputStream();
            byte[] buff = new byte[1024];
            int n;
            while ((n = in.read(buff)) != -1) {
                out.write(buff, 0, n);
                out.flush();
            }

            in.close();
        }
        catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    @GetMapping("/header/getById")
    public void getHeaderById(Long id, HttpServletResponse response) {
        Account account = accountMapper.selectById(id);
        if (account == null) {
            throw new RuntimeException("账号不存在");
        }

        //  设置响应头
        response.setContentType("application/force-download");
        response.addHeader("Content-Disposition", "attachment;fileName=" + account.getId() + ".png");

        try {
            FileInputStream in = new FileInputStream(FILE_BASE_PATH + "image/header/" + account.getId() + ".png");
            ServletOutputStream out = response.getOutputStream();
            byte[] buff = new byte[1024];
            int n;
            while ((n = in.read(buff)) != -1) {
                out.write(buff, 0, n);
                out.flush();
            }

            in.close();
        }
        catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    @PostMapping("/header/upload")
    @TokenVerify
    public Result<?> uploadHeader(HttpServletRequest request) {

        MultipartFile header = ((MultipartHttpServletRequest) request).getFile("header");

        if (header == null || header.isEmpty()) {
            throw new RuntimeException("文件为空");
        }

        //  判断文件类型
        String type = header.getContentType();
        System.out.println(type);
        if (type == null || !type.contains("image")) {
            throw new RuntimeException("文件类型错误");
        }

        //  判断文件大小
        long size = header.getSize();
        if (size > 1024 * 1024 * 10) {
            throw new RuntimeException("文件大于10MB");
        }

        //  获取id
        String id = request.getHeader("arg0");

        //  账号查询
        Account account = accountMapper.selectById(id);
        if (account == null) {
            throw new RuntimeException("账号不存在");
        }

        //  头像像素判断
        BufferedImage bi;
        try {
            bi = ImageIO.read(header.getInputStream());
            if (bi.getWidth() != bi.getHeight()) {
                throw new RuntimeException("图片尺寸错误");
            }
        }
        catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        //  写入文件
        try {
            File to = new File(FILE_BASE_PATH + "image/header/" + id + ".png");
            ImageIO.write(bi, "png", to);
        }
        catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }

        return Result.success().message("上传成功");
    }

    @PostMapping("/paper/image/upload")
    @TokenVerify
    public Result<?> uploadPaperImage(HttpServletRequest request) {

        MultipartFile header = ((MultipartHttpServletRequest) request).getFile("paperImage");

        if (header == null || header.isEmpty()) {
            throw new RuntimeException("文件为空");
        }

        //  判断文件类型
        String type = header.getContentType();
        System.out.println(type);
        if (type == null || !type.contains("image")) {
            throw new RuntimeException("文件类型错误");
        }

        //  判断文件大小
        long size = header.getSize();
        if (size > 1024 * 1024 * 10) {
            throw new RuntimeException("文件大于10MB");
        }

        //  获取id
        String id = request.getHeader("arg0");

        //  账号查询
        Account account = accountMapper.selectById(id);
        if (account == null) {
            throw new RuntimeException("账号不存在");
        }

        //  写入文件
        UUID uuid = UUID.randomUUID();
        try {
            BufferedImage bi = ImageIO.read(header.getInputStream());
            File to = new File(FILE_BASE_PATH + "image/paper/" + id + "-" + uuid + ".png");
            ImageIO.write(bi, "png", to);
        }
        catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }

        return Result.success("上传成功", uuid.toString());
    }

    @GetMapping("/paper/image/get")
    public void getPaperImage(Long id, String uuid, HttpServletResponse response) {

        //  设置响应头
        response.setContentType("application/force-download");
        response.addHeader("Content-Disposition", "attachment;fileName=" + uuid + ".png");

        try {
            FileInputStream in = new FileInputStream(FILE_BASE_PATH + "image/paper/" + id + "-" + uuid + ".png");
            ServletOutputStream out = response.getOutputStream();
            byte[] buff = new byte[1024];
            int n;
            while ((n = in.read(buff)) != -1) {
                out.write(buff, 0, n);
                out.flush();
            }

            in.close();
        }
        catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }
}
